package com.cjdx.supermarket.util;

import java.security.MessageDigest;
import java.util.UUID;

/**
 * 密码工具类
 * 
 * <p>提供密码加密、加盐、验证等相关功能</p>
 * <p>主要功能包括：</p>
 * <ul>
 *   <li>MD5加密</li>
 *   <li>生成随机盐值</li>
 *   <li>密码加盐处理</li>
 *   <li>密码验证</li>
 * </ul>
 * 
 * @author ct.team
 * @version 1.0
 * @since 2023-06-01
 */
public class PasswordUtil {

    /**
     * MD5加密处理
     * 
     * @param s 要加密的原始字符串
     * @return 加密后的十六进制字符串
     * @throws RuntimeException 如果加密过程中发生错误
     */
    private static String md5(String s) {
        try {
            // MessageDigest是封装md5算法的工具对象还支持SHA算法
            MessageDigest md = MessageDigest.getInstance("MD5");
            //通过digest拿到的任意字符串,得到的bates都是等长的
            byte[] bytes = md.digest(s.getBytes("utf-8"));
            return toHex(bytes);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    private static String toHex(byte[] bytes) {
        //toHex的字符串把二进制转换成十六进制
        final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
        StringBuilder ret = new StringBuilder(bytes.length * 2);
        //循环判断是为了补位操作
        for (int i=0; i<bytes.length; i++) {
            ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);
            ret.append(HEX_DIGITS[bytes[i] & 0x0f]);
        }
        return ret.toString();
    }

    /**
     * 生成随机盐值
     * 
     * <p>使用UUID生成唯一识别码，取第一个-前面的部分作为8位随机盐值</p>
     * 
     * @return 8位随机字符串作为盐值
     */
    public static String salt(){
        //使用UUID通用唯一识别码,取第一个-前面的值
        UUID uuid = UUID.randomUUID();
        String[] arr = uuid.toString().split("-");
        return arr[0];
    }

    /**
     * 对密码进行默认加密加盐操作
     * 
     * <p>先对密码进行MD5加密，然后生成随机盐值，将盐值插入到加密后的字符串中</p>
     * 
     * @param password 原始密码字符串
     * @return 加密加盐后的密码字符串
     * 
     * @see #md5(String) 使用的加密方法
     * @see #salt() 使用的盐值生成方法
     */
    public static String encodeDefaultSalt(String password){
        //加密
        String hexPwd = md5(password);
        //生成盐
        String salt = salt();
        System.out.println("salt ：" + salt);
        //加盐操作
        StringBuilder builder = new StringBuilder(hexPwd);
        builder.insert(18, salt);
        //返回加密加盐后的字符串
        return builder.toString();
    }


    public static String encode(String password, String salt){
        //加密
        String hexPwd = md5(password);
        //加盐操作
        StringBuilder builder = new StringBuilder(hexPwd);
        builder.insert(18, salt);
        //返回加密加盐后的字符串
        return builder.toString();
    }

    /**
     * 验证密码是否匹配
     * 
     * <p>通过去除盐值后比较MD5加密结果来验证密码是否正确</p>
     * 
     * @param password 用户输入的原始密码
     * @param dbPassword 数据库中存储的加密加盐后的密码
     * @return true表示密码匹配，false表示不匹配
     * 
     * @see #md5(String) 使用的加密方法
     * @see #encodeDefaultSalt(String) 加密加盐方法
     */
    public static boolean match(String password, String dbPassword){
        StringBuilder builder = new StringBuilder(dbPassword);
        //去盐操作，生成md5加密后原始字符
        builder.replace(18, 26, "");
        //加密新密码，生成md5加密字符
        password = md5(password);
        //校对加密字符与原始字符是否匹配
        return password.equals(builder.toString());
    }

    public static void main(String[] args) {
//        String password = "cndsHFHknvildhnoiseygh/;'.''..";
        String password = "123321";
        String encode = encodeDefaultSalt(password);
        System.out.println(encode); //加密后的密码
        System.out.println(match(password, encode));
    }

}
